﻿using TheOutLetLibrary.Infraestrutura;
using System.Xml;
using System.Xml.Linq;
using System.Collections.Generic;
using System.Collections;
using System;
using System.Linq;
using System.Text;
using System.Data.OleDb;
using System.Threading;
using System.Globalization;

namespace TheOutLetLibrary.Dominio {

    public class CarregadorNF {

        private IFactoryDAO factoryDAO;
        private XNamespace ad = "http://www.portalfiscal.inf.br/nfe";
        private NotaFiscal notaFiscal;
        private Remessa remessaNF;

        public CarregadorNF(IFactoryDAO factory, int idEmpresa) {
            factoryDAO = factory;
            CriaRemessa(idEmpresa);
        }

        private void CriaRemessa(int idEmpresa) {

            using(OleDbConnection conexao = factoryDAO.Conexao) {

                OleDbTransaction transacao = null;
                conexao.Open();
                transacao = conexao.BeginTransaction();

                IRemessaDAO remessaDAO = factoryDAO.GetRemessaNFDAO();
                remessaDAO.Transacao = transacao;

                remessaNF = new Remessa {
                    XID_EMPRESA = idEmpresa,
                    XDT_RECEBIMENTO_REMESSA = System.DateTime.Now
                };

                remessaNF.XID_REMESSA = remessaDAO.IncluiRemessa(remessaNF);
                transacao.Commit();

            }

        }

        public string ImportaNF(string nomeArquivoXml) {

            string mensagem = "Carga efetuada com sucesso";

            try {
                CarregaNF(nomeArquivoXml);
                SalvaContextoNF();
            } catch(Exception ex) {
                mensagem = ex.Message;
            }

            return mensagem;
        }

        private void CarregaNF(string NomeArquivoXml) {

            XElement notaFiscalXml = XElement.Load(NomeArquivoXml);

            XElement cabecalho = notaFiscalXml.Descendants(ad + "ide").First();

            notaFiscal = new NotaFiscal {
                XID_REMESSA = remessaNF.XID_REMESSA,
                XID_EMPRESA = remessaNF.XID_EMPRESA,
                NR_NF = cabecalho.Element(ad + "nNF").Value,
                DT_EMISSAO_NF = DateTime.Parse(cabecalho.Element(ad + "dEmi").Value),
            };

            IEnumerable<XElement> itensNF = from item in notaFiscalXml.Descendants(ad + "prod")
                                            select item;

            Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
            Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");

            foreach(XElement item in itensNF) {
                notaFiscal.ItensNotaFiscal.Add(new ItemNotaFiscal {
                    //XID_PRODUTO = 1,
                    //xID_PRODUTO_NOTA_FISCAL = 1,
                    xID_REMESSA = notaFiscal.XID_REMESSA,
                    PRECO_NF_CONSIGNADO = decimal.Parse(item.Element(ad + "vUnCom").Value),
                    QT_ENVIADA = decimal.ToInt32(decimal.Parse(item.Element(ad + "qCom").Value)),
                    VL_TOTAL = decimal.Parse(item.Element(ad + "vProd").Value),
                    VL_UNITARIO = decimal.Parse(item.Element(ad + "vUnCom").Value),
                });
                notaFiscal.NR_TOTAL_DE_PECAS_INFORMADAS +=
                    decimal.ToInt32(decimal.Parse(item.Element(ad + "qCom").Value));
            }

            foreach(XElement item in itensNF) {
                notaFiscal.ProdutosNotaFiscal.Add(new Produto {
                    XID_EMPRESA = notaFiscal.XID_EMPRESA,
                    CD_MODELO_MARCA = item.Element(ad + "cProd").Value,
                    DSC_MODELO_MARCA = item.Element(ad + "xProd").Value,
                    DSC_MODELO_TOTLET = item.Element(ad + "xProd").Value,
                    NCM = item.Element(ad + "NCM").Value,
                    CFOP = item.Element(ad + "CFOP").Value,
                    PRECO_CONSIGNADO = decimal.Parse(item.Element(ad + "vUnCom").Value),
                    PRECO_POR = decimal.Parse(item.Element(ad + "vProd").Value)
                });
            }

            Thread.CurrentThread.CurrentCulture = new CultureInfo("pt-BR");
            Thread.CurrentThread.CurrentUICulture = new CultureInfo("pt-BR");

        }

        private void SalvaContextoNF() {

            using(OleDbConnection conexao = factoryDAO.Conexao) {

                OleDbTransaction transacao = null;

                try {

                    conexao.Open();
                    transacao = conexao.BeginTransaction();

                    // Inclui registro na tabela tb_nota_fiscal
                    INotaFiscalDAO nfDAO = factoryDAO.GetNotaFiscalDAO();
                    nfDAO.Transacao = transacao;
                    nfDAO.IncluiNotaFiscal(notaFiscal);

                    IItemNotaFiscalDAO itemNFDAO = factoryDAO.GetItemNotaFiscalDAO();
                    itemNFDAO.Transacao = transacao;
                    IProdutoDAO produtoDAO = factoryDAO.GetProdutoDAO();
                    produtoDAO.Transacao = transacao;

                    for(int i = 0; i < notaFiscal.ItensNotaFiscal.Count; i++) {
                        Produto produto = notaFiscal.ProdutosNotaFiscal[i];
                        ItemNotaFiscal itemNF = notaFiscal.ItensNotaFiscal[i];
                        itemNF.XID_PRODUTO = produtoDAO.AcheOuInclua(produto);
                        itemNF.XID_NOTA_FISCAL = notaFiscal.XID_NOTA_FISCAL;
                        itemNFDAO.Inclui(itemNF);
                    }

                    //// Inclui registros na tabela rl_produto_nota_fiscal
                    //IItemNotaFiscalDAO itemNFDAO = factoryDAO.GetItemNotaFiscalDAO();
                    //itemNFDAO.Transacao = transacao;
                    //foreach(ItemNotaFiscal itemNF in notaFiscal.ItensNotaFiscal) {
                    //    itemNF.XID_NOTA_FISCAL = notaFiscal.XID_NOTA_FISCAL;
                    //    itemNFDAO.Inclui(itemNF);
                    //}

                    //// Atualializa tb_produto, incluindo produtos que ainda não estejam cadastrados
                    //IProdutoDAO produtoDAO = factoryDAO.GetProdutoDAO();
                    //produtoDAO.Transacao = transacao;
                    //foreach(Produto produtoNF in notaFiscal.ProdutosNotaFiscal) {
                    //    produtoDAO.AcheOuInclua(produtoNF);
                    //}

                    transacao.Commit();

                } catch(Exception) {
                    transacao.Rollback();
                    throw;
                }

            }

        }

    }

}
